﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ExecutionContract
{
    public class ExecutionContractServiceExtender : IExecutionContractServiceExtender
    {
        public Tuple<object, Tuple<string, object>[]> Execute(string _assembly, string _datacontractEntity, string _methodName, Tuple<string, object>[] _properties, object[] _params)
        {
            Assembly assembly = System.Reflection.Assembly.Load(_assembly);

            Type type = assembly.GetType(_datacontractEntity);

            //BE CAREFUL object has to have an empty constructor
            object retObj = type.GetConstructor(Type.EmptyTypes).Invoke(null);
            PropertyInfo propertyInfo;
            PropertyInfo[] allProperties = new PropertyInfo[_properties.Length];
            int count = 0;
            //set the properties to create a copy of the object on client side
            foreach (Tuple<string, object> property in _properties)
            {
                propertyInfo = type.GetProperty(property.Item1);
                propertyInfo.SetValue(retObj, property.Item2, null);

                //save the propertyInfos in an array to avoid unnessecary reflection operations
                allProperties[count] = propertyInfo;
                count++;
            }

            MethodInfo mi = type.GetMethod(_methodName);

            Object result = mi.Invoke(retObj, _params);
            
            //find out which properties have changed
            Object temp;
            count = 0;
            List<Tuple<string, object>> changedProperties = new List<Tuple<string, object>>();
            foreach (PropertyInfo propInfo in allProperties)
            {
                temp = propInfo.GetValue(retObj, null);
                if (!temp.Equals(_properties[count].Item2))
                {
                    changedProperties.Add(new Tuple<string,object>(propInfo.Name,temp));
                }
                count++;
            }

            return new Tuple<object, Tuple<string, object>[]>(result, changedProperties.ToArray());
        }
    }
}
